#!/usr/bin/perl
#use strict;
#use warnings;
use File::stat;
use File::Basename;
use MP3::Tag;
#use Cwd qw (cwd);

### global variables ###

@warnings = ();

### main ###

if (system('mkdir recoded')) {
        print_error('cannot mkdir') if (!-d 'recoded');
};

my $jar_file_name = 'id3iconv-0.2.1.jar';
my $encoding = 'cp1251';
my $convert_id3_tags = 0;
my $rename_only = 0;
my $rename_all_files = 0;
my $pretend = 0;
my $file_opreation = 'cp -rpf';
get_options();
my $jar_file = File::Basename::dirname($0) . '/' . $jar_file_name;
%genres = ();
get_genres();
recode_tracks();

### procedures ###

sub get_genres {
    open(GENRES, "id3v2 --list-genres |");
#    my @output = <GENRES>;
    foreach (<GENRES>) {
        chomp;
        s/^\s+//;
        s/\s+$//;
        /(:\s+)/;
        $genres{$'} = $`;
#        print "$' : $`\n";
    };
    close GENRES;
};

sub get_options {
    while (my $arg = shift @ARGV) {
        if ($arg =~ /^-u$/) {
            $convert_id3_tags++;
#            $encoding = shift @ARGV if (($ARGV[0] =! /^-/) && ($ARGV[0] != 1));
            next;
        };
        if ($arg =~ /^--help$/ || $arg =~ /^-h$/) {
            print_usage();
        }; 
        if ($arg =~ /^--rename_only$/ || $arg =~ /^-r$/) {
            $rename_only++;
        }; 
        if ($arg =~ /^--rename_all_files$/) {
            $rename_all_files++;
        }; 
        if ($arg =~ /^--move$/ || $arg =~ /^-r$/) {
            $move_files++;
        }; 
        if ($arg =~ /^-p$/) {
            $pretend++;
        }; 
    };
    if ($rename_all_files && (!$rename_only)) {
        print_error("\"--rename_all_files\" is for use with \"--rename_only\" anly\n");
    };
    $file_opreation = 'mv' if ($move_files && !$convert_id3_tags);
};

sub print_usage {
    print STDERR "\nrecode_mp3\n";
    print STDERR "Syntax:    recode_mp3 [-d PATH_TO_MP3s] [-x TEXT_TO_REMOVE] [-p] [-u|--unicode [ORIGINAL_ENCODING]] [-r|--rename_only] --rename_all_files\n";
    print STDERR "        -d     - path to directory where mp3s are located\n";
    print STDERR "        -x     - exlude text from the filenames\n";
    print STDERR "        -p     - pretend, just show what is gonna be made\n";
    print STDERR "        -u     - convert ID3 tags to unicode, default initial encoding is $encoding\n";
    print STDERR "                 needs $jar_file_name in the same directory as the recode_mp3.pl\n";
    print STDERR "        -r     - only rename tracs\n";
    print STDERR "        --rename_all_files     - rename all files (not only mp3)\n";
    print STDERR "        --move     - move files instead of copying\n";
    exit(0);
};

sub quote_spec_chars {
        my $string = shift;
        $$string =~ s/\(/\\\(/g;
        $$string =~ s/\)/\\\)/g;
        $$string =~ s/\'/\\\'/g;
        $$string =~ s/\s/\\ /g;
        $$string =~ s/\&/\\\&/g;
        #return $string;
};

sub recode_tracks {
    if (!opendir(DIR_HANDLE, '.')) {
            print_error('Cannot open current directory');
    };
    my @mp3_files = ();
    foreach my $entry (sort readdir(DIR_HANDLE)) {
    	my $orig_name = $entry;
        next if ($entry =~ /^\.+$/);
        if (!$rename_all_files) {
            next if (lc($entry) !~ /\.mp3$/);
        };
        $entry = "\"$entry\"";            
        next if (-d $entry);
	push (@mp3_files, $entry);
	
        if ($rename_only) {
        if ($convert_id3_tags) {
            my $convert_id3_tags_string = "java -jar $jar_file";
            $convert_id3_tags_string .= " -e $encoding" if ($convert_id3_tags);
            $convert_id3_tags_string .= " $new_name";
            run_system_call($convert_id3_tags_string); 
        };
            next;
        };
    };
    closedir DIR_HANDLE;
    print "Renaming tracks...\n";
    my $number = 0;
    my $number_length = length(@mp3_files);
    $number_length = 2 if (length(@mp3_files) < 2);

    foreach $entry (@mp3_files) {
	$number++;
        my $number_string = "$number";
        while (length($number_string) != $number_length) {
            $number_string = "0" . $number_string;
        };
        my $new_name = $number_string . "." . $entry;
        quote_spec_chars(\$new_name);
        $new_name = 'recoded/' . $new_name;
        my $new_name_unquoted = $new_name;
        system "ls $entry";
	if ($pretend) {
	    print ("$file_opreation $entry $new_name\n");
	} else {
            run_system_call("$file_opreation $entry $new_name");
	};
    }
    exit;
};


sub correct_idv2tag {
    my ($source_file, $new_file) = @_;#($entry, $new_name)
    open(ID3V2INFO, "id3info $source_file |");
    my @idv3inf = <ID3V2INFO>;
    close ID3V2INFO;
    my $last_frame;
    my %frames_info = ();
    foreach (@idv3inf) {
        chomp;
        /(:)/;
        my $frame = $`;
        my $info = $';
        $info =~s/^\s+//;
        $info =~s/\s+$//;
        if ($frame =~ /===\s(\S+)/) {
            $last_frame = $1;
            if ($last_frame eq 'TCON') {
                $info =~ s/^(\(\d+\)\s*)//;
            };
            $frames_info{$last_frame} = $info;
        } else {
            $frames_info{$last_frame} .= "\n$info";
        };

    };
    my $id3tag_string = '/usr/bin/id3v2 ';
    if (defined $frames_info{TOPE}) {
        $id3tag_string .= "-a \"$frames_info{TOPE}\" ";
    } elsif (defined $frames_info{TPE1}) {
        $id3tag_string .= "-a \"$frames_info{TPE1}\" ";
    };
    $id3tag_string .= "-T \"$frames_info{TRCK}\" " if defined $frames_info{TRCK};
    $id3tag_string .= "-t \"$frames_info{TIT2}\" " if defined $frames_info{TIT2};
    $id3tag_string .= "-A \"$frames_info{TALB}\" " if defined $frames_info{TALB};
    $id3tag_string .= "-y \"$frames_info{TYER}\" " if defined $frames_info{TYER};
    $id3tag_string .= "-g $genres{$frames_info{TCON}} " if defined $genres{$frames_info{TCON}};
    $id3tag_string .= $new_file;
#    print "$_ $frames_info{$_}\n" foreach (keys %frames_info);
    system ($id3tag_string);
};

sub cp_ID3v1_tag {
    my ($source_file, $new_file) = @_;#($entry, $new_name)
    my $mp3 = MP3::Tag->new($source_file);
#    $mp3->get_tags();
    my $id3v1 = undef;
    $id3v1 = $mp3->{ID3v1} if exists $mp3->{ID3v1};
    if (defined $id3v1) {
        my $mp3_new = MP3::Tag->new($new_file);
        my $id3v1_new = $mp3_new->new_tag("ID3v1");
        $artist  = $id3v1_new->artist($id3v1->$artist);
        $album   = $id3v1_new->album($id3v1->$album);
        $year    = $id3v1_new->year($id3v1->$year);
        $comment = $id3v1_new->comment($id3v1->$comment);
        $track   = $id3v1_new->track($id3v1->$track);
        $genre   = $id3v1_new->genre($id3v1->$genre);
        $id3v1_new->write_tag();
    };
};
sub run_system_call {
    my $system_command = shift;
        if ($pretend) {
        print $system_command . "\n";
        return;
    };
    system($system_command);
};

sub print_error {
    my $message = shift;
    $message = "\nError:" . $message . "\n";
    print STDERR $message;
    exit(1);
};

sub print_warnings {
    return if (!scalar @warnings);
    foreach $warning (@warnings) {
        print STDERR "\nWARNING: $warning\n";
    };
};
